<template>
  <el-drawer
    :title="drawerTitle[drawerType]"
    size="60%"
    :visible.sync="drawerVisible"
    direction="rtl"
    :close-on-press-escape="false"
    :wrapperClosable="false"
    :destroy-on-close="true"
    :before-close="beforeClose"
    custom-class="tag-drawer pac-drawer"
  >
    <div class="drawer-wrap">
      <div class="drawer-content tag-scrollbar">
        <el-form :model="editForm" :rules="editFormRules" ref="editForm" label-width="0">
          <div class="content-divider first">
            <div class="clearfix">
              <div class="number">01</div>
              <div class="divider-title">基本信息<br />Essential information</div>
              <div class="bg"></div>
            </div>
          </div>
          <el-row :gutter="20">
            <el-col :span="24">
              <div class="source-item">
                <div class="star" v-if="drawerType !== 'view'"></div>
                <div class="source-title linear-blue">API名称</div>
                <div class="source-content">
                  <el-form-item prop="apiNm">
                    <el-input
                      v-model="editForm.apiNm"
                      placeholder="请输入API名称"
                      :disabled="drawerType === 'view'"
                    ></el-input>
                  </el-form-item>
                </div>
              </div>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <div class="source-item">
                <div class="star" v-if="drawerType !== 'view'"></div>
                <div class="source-title linear-purpose">请求方式</div>
                <div class="source-content">
                  <el-form-item prop="apiReqType">
                    <el-select v-model="editForm.apiReqType" :disabled="drawerType === 'view'">
                      <el-option label="---" value=""></el-option>
                      <el-option
                        v-for="item in $dictList('$api_request_type')"
                        :key="item.key"
                        :label="item.value"
                        :value="item.key"
                      ></el-option>
                    </el-select>
                  </el-form-item>
                </div>
              </div>
            </el-col>
            <el-col :span="12">
              <div class="source-item">
                <div class="star" v-if="drawerType !== 'view'"></div>
                <div class="source-title linear-purpose">格式结果</div>
                <div class="source-content">
                  <el-form-item prop="apiRespFormat">
                    <el-select v-model="editForm.apiRespFormat" :disabled="drawerType === 'view'">
                      <el-option label="---" value=""></el-option>
                      <el-option
                        v-for="item in apiRespFormatList"
                        :key="item.val"
                        :label="item.label"
                        :value="item.val"
                      ></el-option>
                    </el-select>
                  </el-form-item>
                </div>
              </div>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <div class="source-item">
                <div class="star" v-if="drawerType !== 'view'"></div>
                <div class="source-title linear-green" style="padding-left: 40px">数据平台个数</div>
                <div class="source-content">
                  <el-form-item prop="apiType" :class="{ disabled: drawerType === 'view' }">
                    <el-radio-group v-model="editForm.apiType" :disabled="drawerType === 'view'">
                      <el-radio :label="1">单个</el-radio>
                      <el-radio :label="2">多个</el-radio>
                    </el-radio-group>
                  </el-form-item>
                </div>
              </div>
            </el-col>
            <el-col :span="12">
              <div class="source-item">
                <div class="star" v-if="drawerType !== 'view'"></div>
                <div class="source-title linear-green">请求路径</div>
                <div class="source-content">
                  <el-form-item prop="apiPath">
                    <el-input
                      v-model="editForm.apiPath"
                      placeholder="请输入请求路径"
                      :disabled="drawerType === 'view'"
                    ></el-input>
                  </el-form-item>
                </div>
              </div>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="24">
              <div class="source-item desc-item">
                <div class="source-title linear-cyan">API说明</div>
                <div class="source-content">
                  <el-form-item prop="apiDesc">
                    <el-input
                      placeholder="请输入API说明"
                      v-model="editForm.apiDesc"
                      type="textarea"
                      :maxlength="1000"
                      :rows="5"
                      resize="none"
                      :show-word-limit="true"
                      :disabled="drawerType === 'view'"
                    ></el-input>
                  </el-form-item>
                </div>
              </div>
            </el-col>
          </el-row>
          <div class="content-divider second">
            <div class="clearfix">
              <div class="number">02</div>
              <div class="divider-title">参数信息<br />Parameter information</div>
              <div class="bg"></div>
            </div>
          </div>
          <el-row :gutter="20">
            <el-col :span="24">
              <div class="source-item params-item">
                <div class="source-title">
                  <span><icon-svg name="iconArts"></icon-svg></span><br />
                  参数信息
                </div>
                <div class="source-content">
                  <el-form-item
                    prop="apiReqContext"
                    class="code-input"
                    :class="{ 'disable-item': drawerType === 'view' }"
                  >
                    <textarea id="api-req-box"></textarea>
                    <el-input v-model="editForm.apiReqContext" type="textarea" :style="codeStyle"></el-input>
                  </el-form-item>
                </div>
              </div>
            </el-col>
          </el-row>
          <div class="content-divider third">
            <div class="clearfix">
              <div class="number">03</div>
              <div class="divider-title">返回结果<br />Return result</div>
              <div class="bg"></div>
            </div>
          </div>
          <div class="result-wrap">
            <el-row class="result-title">
              <el-col :span="8">Code</el-col>
              <el-col :span="16">Description</el-col>
            </el-row>
            <div v-for="(item, index) in editForm.apiRespContext" :key="index" class="result-item">
              <el-row>
                <el-col :span="8" align="center">
                  <template v-if="item.code === 200 && index === 0">{{ item.code }}</template>
                  <el-form-item
                    :prop="'apiRespContext.' + index + '.code'"
                    :rules="[
                      { required: true, message: 'code编码不能为空', trigger: 'blur' },
                      { type: 'number', message: 'code只能输入数字', trigger: 'blur' }
                    ]"
                    v-else
                  >
                    <el-input-number
                      placeholder="请输入code编码"
                      v-model="item.code"
                      :step-strictly="true"
                      :disabled="drawerType === 'view'"
                    ></el-input-number>
                  </el-form-item>
                </el-col>
                <el-col :span="16">
                  <el-form-item
                    :prop="'apiRespContext.' + index + '.desc'"
                    :rules="[{ required: true, message: '描述信息不能为空', trigger: 'blur' }]"
                  >
                    <el-input
                      placeholder="请输入描述信息"
                      v-model="item.desc"
                      :disabled="drawerType === 'view'"
                    ></el-input>
                  </el-form-item>
                  <template v-if="item.code === 200 && index === 0">
                    <p>Example Value</p>
                    <el-form-item
                      :prop="'apiRespContext.' + index + '.example'"
                      :rules="[
                        { validator: isJSON, trigger: 'blur' },
                        { required: true, message: '示例数据不能为空', trigger: 'blur' }
                      ]"
                      class="result-text-box code-input"
                      :class="{ 'disable-item': drawerType === 'view' }"
                    >
                      <textarea id="api-resp-box"></textarea>
                      <el-input v-model="item.example" type="textarea" resize="none" :style="codeStyle"></el-input>
                    </el-form-item>
                  </template>
                </el-col>
              </el-row>
              <div class="result-handler" v-if="drawerType !== 'view'">
                <el-button icon="el-icon-plus" type="primary" size="mini" circle @click="addResult(index)"></el-button>
                <el-button
                  icon="el-icon-minus"
                  type="primary"
                  size="mini"
                  circle
                  @click="deleteResult(index)"
                  v-if="item.code !== 200 && index !== 0"
                ></el-button>
              </div>
            </div>
          </div>
        </el-form>
      </div>
    </div>
    <div class="drawer-btns">
      <template v-if="drawerType === 'add' || drawerType === 'edit'">
        <el-button @click="beforeClose">取消</el-button>
        <el-button type="primary" size="medium" @click="submit">保存</el-button>
      </template>
      <el-button type="primary" size="medium" @click="beforeClose" v-else>关闭</el-button>
    </div>
  </el-drawer>
</template>

<script>
import CodeMirror from 'codemirror'
export default {
  data() {
    const isJSON = (rule, value, callback) => {
      if (!value) return callback()
      try {
        var obj = JSON.parse(value)
        if (obj && typeof obj === 'object') {
          return callback()
        } else {
          return callback(new Error('请输入正确的JSON格式数据'))
        }
      } catch (e) {
        return callback(new Error('请输入正确的JSON格式数据'))
      }
    }
    const checkPath = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('请求路径不能为空'))
      } else {
        let patt = /^\/[a-zA-Z0-9_{}/]*[a-zA-Z0-9_}]$/
        if (!patt.test(value)) {
          return callback(new Error('请求路径只能以/开头,由字母, 数字, / , _ ，{}, 等字符组成,并且不能以/结尾'))
        } else {
          return callback()
        }
      }
    }
    return {
      editable: true,
      drawerType: 'add',
      drawerTitle: {
        view: '标签API详情',
        add: '添加标签API',
        edit: '编辑标签API'
      },
      drawerVisible: false,
      apiRespFormatList: [{ label: 'JSON', val: 1 }],
      editForm: {
        apiId: '',
        apiNm: '',
        apiPath: '',
        apiType: 1,
        apiReqType: '',
        apiRespFormat: '',
        apiDesc: '',
        apiReqContext: '',
        apiRespContext: [{ code: 200, desc: 'OK', example: '' }]
      },
      editFormRules: {
        apiNm: [
          { required: true, message: '接口名称不能为空', trigger: 'blur' },
          { max: 64, message: '接口名称不能超过64个字符', trigger: 'blur' }
        ],
        apiPath: [
          { validator: checkPath, trigger: 'blur' },
          { max: 100, message: '请求路径不能超过100个字符', trigger: 'blur' }
        ],
        apiReqType: [{ required: true, message: '请求方式不能为空', trigger: 'change' }],
        apiRespFormat: [{ required: true, message: '格式结果不能为空', trigger: 'change' }],
        apiDesc: [{ max: 1000, message: 'API说明不能超过1000个字符', trigger: 'blur' }],
        apiReqContext: [
          { validator: isJSON, trigger: 'blur' },
          { max: 1000, message: '参数信息不能超过1000个字符', trigger: 'blur' }
        ]
      },
      apiReqEditor: null,
      apiRespEditor: null,
      codeStyle: {
        height: 0,
        overflow: 'hidden'
      }
    }
  },
  methods: {
    isJSON(rule, value, callback) {
      if (!value) return callback()
      try {
        var obj = JSON.parse(value)
        if (obj && typeof obj === 'object') {
          return callback()
        } else {
          return callback(new Error('请输入正确的JSON格式数据'))
        }
      } catch (e) {
        return callback(new Error('请输入正确的JSON格式数据'))
      }
    },
    showDrawer(params) {
      this.drawerType = params.action
      this.drawerVisible = true
      if (this.drawerType === 'edit' || this.drawerType === 'view') {
        this.editForm.apiId = params.apiId
        this.getApiDetail()
      }
      this.$nextTick(() => this.initText())
    },
    initText() {
      if (!this.apiReqEditor) {
        this.apiReqEditor = CodeMirror.fromTextArea(document.getElementById('api-req-box'), {
          mode: 'application/json',
          lineWrapping: true,
          foldGutter: true,
          readOnly: this.drawerType === 'view' ? 'nocursor' : false,
          gutters: ['CodeMirror-foldgutter']
        })
      }
      this.apiReqEditor.setValue(this.editForm.apiReqContext)
      this.apiReqEditor.refresh()
      if (this.drawerType !== 'view') this.apiReqEditor.on('blur', this.resreshReq)
      if (!this.apiRespEditor) {
        this.apiRespEditor = CodeMirror.fromTextArea(document.getElementById('api-resp-box'), {
          mode: 'application/json',
          lineWrapping: true,
          foldGutter: true,
          readOnly: this.drawerType === 'view',
          gutters: ['CodeMirror-foldgutter']
        })
      }
      let resp = this.editForm.apiRespContext.find(item => item.code === 200)
      this.apiRespEditor.setValue(resp.example)
      this.apiRespEditor.refresh()
      if (this.drawerType !== 'view') this.apiRespEditor.on('blur', this.resreshResp)
    },
    resreshReq() {
      let content = this.apiReqEditor.getValue()
      this.editForm.apiReqContext = content
      this.$refs.editForm.validateField('apiReqContext')
    },
    resreshResp() {
      let content = this.apiRespEditor.getValue()
      this.editForm.apiRespContext[0].example = content
      this.$refs.editForm.validateField('apiRespContext.0.example')
    },
    getApiDetail() {
      this.$ajax({
        url: this.$ajax.setUrl(`pac/pacApi/${this.editForm.apiId}`),
        method: 'get',
        params: this.$ajax.setParams()
      }).then(({ data }) => {
        if (data && data.code === '0') {
          if (data.data) {
            this.editForm.apiNm = data.data.apiNm
            this.editForm.apiPath = this.drawerType === 'view' ? data.data.apiUrl : data.data.apiPath
            this.editForm.apiType = data.data.apiType
            this.editForm.apiRespFormat = data.data.apiRespFormat
            this.editForm.apiDesc = data.data.apiDesc
            this.editForm.apiReqContext = data.data.apiReqContext
            this.editForm.apiReqType = data.data.apiReqType
            this.editForm.apiRespContext = JSON.parse(data.data.apiRespContext)
            this.$nextTick(() => this.initText())
          }
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    addResult(index) {
      this.editForm.apiRespContext.splice(index + 1, 0, { code: '', desc: '' })
    },
    deleteResult(index) {
      this.editForm.apiRespContext.splice(index, 1)
    },
    beforeClose() {
      this.clearForm()
      this.drawerVisible = false
    },
    submit() {
      this.$refs.editForm.validate(valid => {
        if (valid) {
          let respContext = this.editForm.apiRespContext
          let resp = new Set()
          respContext.forEach(item => resp.add(item.code))
          if (respContext.length !== resp.size) {
            this.$message.error('返回结果code不能重复')
            return
          }
          let arg = {
            apiDesc: this.editForm.apiDesc,
            apiNm: this.editForm.apiNm,
            apiPath: this.editForm.apiPath,
            apiType: this.editForm.apiType,
            apiReqContext: this.editForm.apiReqContext,
            apiReqType: this.editForm.apiReqType,
            apiRespContext: JSON.stringify(this.editForm.apiRespContext),
            apiRespFormat: this.editForm.apiRespFormat
          }
          if (this.drawerType === 'edit') arg.apiId = this.editForm.apiId
          this.$ajax({
            url: this.$ajax.setUrl('pac/pacApi'),
            method: this.drawerType === 'edit' ? 'put' : 'post',
            data: this.$ajax.setData(arg)
          }).then(({ data }) => {
            if (data && data.code === '0') {
              this.$message.success(data.msg)
              this.beforeClose()
              this.$emit('refresh')
            } else {
              this.$message.error(data.data || data.msg)
            }
          })
        }
      })
    },
    clearForm() {
      this.editForm.apiId = ''
      this.editForm.apiNm = ''
      this.editForm.apiPath = ''
      this.editForm.apiType = 1
      this.editForm.apiReqType = ''
      this.editForm.apiRespFormat = ''
      this.editForm.apiDesc = ''
      this.editForm.apiReqContext = ''
      this.editForm.apiRespContext = [{ code: 200, desc: 'OK', example: '' }]
      this.apiReqEditor.toTextArea()
      this.apiReqEditor = null
      this.apiRespEditor.toTextArea()
      this.apiRespEditor = null
      this.$nextTick(() => this.$refs.editForm.clearValidate())
    }
  }
}
</script>

<style lang="scss">
.pac-drawer {
  .source-item {
    width: 100%;
    height: 45px;
    margin-bottom: 20px;
    box-shadow: #eee 0 0 10px;
    position: relative;
    &.desc-item {
      height: 117px;
      .source-title {
        line-height: 117px;
      }
      .el-textarea__inner {
        height: 117px;
        border-color: #fff;
      }
    }
    .source-title {
      font-weight: bold;
      width: 150px;
      height: 100%;
      padding-left: 50px;
      line-height: 45px;
      color: #fff;
      position: absolute;
      z-index: 2;
      &:before {
        width: 10px;
        height: 10px;
        content: '';
        background-color: #eee9ff;
        border: 2px solid #cfc7ee;
        margin-top: -5px;
        position: absolute;
        top: 50%;
        left: 20px;
        border-radius: 50%;
      }
      &:after {
        width: 0;
        height: 0;
        content: '';
        margin-top: -10px;
        border-top: 10px solid transparent;
        border-bottom: 10px solid transparent;
        position: absolute;
        top: 50%;
        right: -10px;
      }
      &.linear-blue:after {
        border-left: 10px solid #635fd7;
      }
      &.linear-purpose:after {
        border-left: 10px solid #7c6bed;
      }
      &.linear-green:after {
        border-left: 10px solid #36b999;
      }
      &.linear-cyan:after {
        border-left: 10px solid #0696ec;
      }
    }
    .source-content {
      line-height: 45px;
      padding-left: 150px;
    }
    .el-select .el-input__inner,
    .el-input .el-input__inner {
      height: 45px;
      line-height: 45px;
      border-color: #fff;
    }
  }
  .params-item {
    height: 180px;
    border-top-left-radius: 5px;
    border-bottom-left-radius: 5px;
    overflow: hidden;
    .source-title {
      width: 200px;
      padding-left: 0;
      color: #666;
      text-align: center;
      &:before {
        width: 5px;
        height: 100%;
        content: '';
        border: 0;
        margin-top: 0;
        background-color: #f2a85d;
        position: absolute;
        top: 0;
        left: 0;
        border-radius: 0;
      }
      &:after {
        width: 1px;
        height: auto;
        margin-top: 0;
        content: '';
        background-color: #eee;
        position: absolute;
        top: 10px;
        right: 10px;
        bottom: 10px;
      }
      span {
        display: inline-block;
        width: 50px;
        height: 50px;
        margin-top: 45px;
        color: #fff;
        background-color: #f2a85d;
        text-align: center;
        border-radius: 50%;
        svg {
          width: 30px;
          height: 30px;
          margin-top: 10px;
        }
      }
    }
    .source-content {
      padding: 20px 20px 20px 200px;
      line-height: normal;
      .el-form-item__content {
        line-height: normal;
      }
      .CodeMirror {
        height: 140px;
        border: 1px solid #eee;
      }
    }
  }
  .result-wrap {
    .result-title {
      height: 40px;
      color: #fff;
      background-color: #38abf6;
      text-align: center;
      line-height: 40px;
      border-radius: 5px;
      .el-col {
        height: 100%;
        & + .el-col {
          position: relative;
          &::after {
            width: 1px;
            height: 30px;
            content: '';
            background-color: #fff;
            position: absolute;
            top: 5px;
            left: 0;
          }
        }
      }
    }
    .result-item {
      margin-top: 20px;
      padding: 20px 90px 0 0;
      border-top-left-radius: 5px;
      border-bottom-left-radius: 5px;
      position: relative;
      overflow: hidden;
      box-shadow: 0 2px 2px 0 #eee, 0 0 6px #eee;
      &:before {
        width: 5px;
        content: '';
        background-color: #1e9ffe;
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
      }
      p {
        font-weight: bold;
        color: 000;
        text-indent: 10px;
        margin-bottom: 10px;
      }
      .el-input__inner {
        border-color: #eee;
      }
      .el-input-number {
        width: 100%;
      }
      .el-input-number__decrease,
      .el-input-number__increase {
        display: none;
      }
      .el-col-8 {
        padding: 0 20px;
      }
      .result-handler {
        width: 90px;
        padding: 0 10px;
        position: absolute;
        top: 20px;
        right: 0;
        .el-button {
          margin-top: 5px;
        }
        .el-button--primary {
          background-color: #38abf6;
          border-color: #38abf6;
        }
      }
      .result-text-box {
        margin-bottom: 5px;
        .el-form-item__content {
          line-height: normal;
        }
        .CodeMirror {
          height: 250px;
          border: 1px solid #eee;
        }
      }
    }
  }
  .disable-item .CodeMirror {
    background-color: #f6f6f6;
  }
  .code-input .el-form-item__error {
    margin-top: -15px;
  }
  .el-input.is-disabled .el-input__icon {
    display: none;
  }
  .el-radio-group {
    width: 100%;
    padding: 0 15px;
    line-height: 45px;
  }
  .el-form-item.disabled .el-radio-group {
    background-color: #f6f6f6;
    border: 1px solid #eee;
  }
}
</style>
